﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace FunDraw.LayerInfos
{
    /// <summary>
    /// 方程接口
    /// </summary>
    public interface IntEquation
    {
        /// <summary>
        /// 根据x值获取y值
        /// </summary>
        /// <param name="x">给定的x值</param>
        /// <returns>y值</returns>
        float GetValueFromX(float x);
        /// <summary>
        /// 根据y值获取x值
        /// </summary>
        /// <param name="y">指定的y值</param>
        /// <returns>返回x值</returns>
        float GetValueFromY(float y);
        /// <summary>
        /// 校验方程的有效性
        /// </summary>
        /// <returns>校验结果</returns>
        bool CheckValidity();
        /// <summary>
        /// 判断坐标点是否有效
        /// </summary>
        /// <param name="p">坐标点</param>
        /// <param name="layersize">图层尺寸类</param>
        /// <returns>判断结果</returns>
        bool CheckPointValidity(PointF p);

        /// <summary>
        /// 获取方程类别
        /// </summary>
        /// <returns></returns>
        LAYERTYPE GetEquationType();

        /// <summary>
        /// 绘制对象
        /// </summary>
        /// <param name="g">画布</param>
        void DrawGraph(Graphics g);
        /// <summary>
        /// 擦除对象
        /// </summary>
        /// <param name="g">画布</param>
        void Eraser(Graphics g);

    }

    /// <summary>
    /// 基础方程类
    /// </summary>
    public abstract class BaseEquation
    {
        /// <summary>
        /// 线条颜色
        /// </summary>
        public abstract Color LineColor { get; set; }
        /// <summary>
        /// 线条宽度
        /// </summary>
        public abstract int LineWidth { get; set; }
        /// <summary>
        /// 标签颜色
        /// </summary>
        public abstract Color TagColor { get; set; }
        /// <summary>
        /// 标签字体
        /// </summary>
        public abstract Font TagFont{get;set;}
        /// <summary>
        /// 是否展示标签
        /// </summary>
        public abstract bool ShowTag { get; set; }
        public abstract string TagInfo { get; }
        /// <summary>
        /// 画布背景色
        /// </summary>
        public abstract Color CavasBackColor { get; set; }

        public abstract LayerSize layersize { get; set; }
        /// <summary>
        /// 输入字符串格式的方程
        /// </summary>
        /// <returns></returns>
        public abstract  string toString();

    }
    /// <summary>
    /// 直线方程类
    /// </summary>
    public class LineEquation : BaseEquation, IntEquation
    {

        private float _A = 1;
        private float _B = 1;
        private float _C = 1;
        private Color _LineColor=Color.Red;
        private int _LineWidth=1;
        private Color _TagColor=Color.Red;
        private Font _TagFont = new Font("宋体", 12);
        private bool _ShowTag=true;
        private Color _CavasBackColor=Color.Red;
        /// <summary>
        /// 坐标系尺寸
        /// </summary>
       

        /// <summary>
        /// 直线方程A参数
        /// </summary>
        public float A
        {
            get
            {
                return _A;
            }
            set
            {
                _A = value;
            }
        }
        /// <summary>
        /// 直线方程B参数
        /// </summary>
        public float B
        {
            get
            {
                return _B;
            }
            set
            {
                _B = value;
            }
        }
        /// <summary>
        /// 直线方程C参数
        /// </summary>
        public float C
        {
            get
            {
                return _C;
            }
            set
            {
                _C = value;
            }
        }
        /// <summary>
        /// 线条颜色
        /// </summary>
        public override Color LineColor
        {
            get
            {
                return _LineColor;
            }
            set
            {
                _LineColor = value;
            }
        }
        /// <summary>
        /// 线条宽度
        /// </summary>
        public override int LineWidth
        {
            get
            {
                return _LineWidth;
            }
            set
            {
                _LineWidth = value;
            }
        }
        /// <summary>
        /// 线条颜色
        /// </summary>
        public override Color TagColor 
        {
            get
            {
                return _TagColor;
            }
            set
            {
                _TagColor = value;
            }
        }
        /// <summary>
        /// 标签字体
        /// </summary>
        public override Font TagFont
        {
            get
            {
                return _TagFont;
            }
            set
            {
                _TagFont = value;
            }
        }

        /// <summary>
        /// 是否展示标签
        /// </summary>
        public override bool ShowTag
        {
            get
            {
                return _ShowTag;
            }
            set
            {
                _ShowTag = value;
            }
        }

        


        /// <summary>
        /// 画布背景色
        /// </summary>
        public override Color CavasBackColor
        {
            get
            {
                return _CavasBackColor;
            }
            set
            {
                _CavasBackColor = value;
            }
        }

        public override LayerSize layersize { get; set; }

        /// <summary>
        /// 获取tag信息
        /// </summary>
        public override string TagInfo
        {
            get
            {
                if (A == 0 && B == 0)
                    return "";
                else
                {
                    string str_x = string.Empty, str_y = string.Empty, str_c = string.Empty;
                    if ((A > 1 || A < 0) && (A != -1))
                        str_x = string.Format("{0}X", A);
                    else if (A == 0)
                        str_x = "";
                    else if (A == 1)
                        str_x = "X";
                    else if (A == -1)
                        str_x = string.Format("{0}X", "-");

                    if (B > 1)
                        str_y = string.Format("+{0}Y", B);
                    else if (B == 1)
                        str_y = "+Y";
                    else if (B == 0)
                        str_y = "";
                    else if (B < 0&&B!=-1)
                        str_y = string.Format("{0}Y", B);
                    else if(B==-1)
                        str_y = string.Format("{0}Y", "-");

                    if (C > 0)
                        str_c = string.Format("+{0}", C);
                    else if (C == 0)
                        str_c = "";
                    else if (C < 0)
                        str_c = string.Format("{0}", C);


                    return string.Format("{0}{1}{2}=0", str_x, str_y, str_c);
                }
            }
        }

        public bool CheckValidity()
        {
            if (A == 0 && B == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 绘制直线
        /// </summary>
        /// <param name="g">画布</param>
        public void DrawGraph(Graphics g)
        {
            try
            {
                Bitmap bmp = new Bitmap(layersize.Width,layersize.Height);
                g.DrawImage(bmp, new Point(0, 0));
                Graphics bg = Graphics.FromImage(bmp);
                bg.SmoothingMode = SmoothingMode.HighQuality; //高质量
                bg.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
                // 初始化线条画笔
                Pen pen = new Pen(LineColor, LineWidth);
                //候选点列表
                List<PointF> list_point = new List<PointF>();
                float x1 = layersize.xMax;
                float y1 = GetValueFromX(x1);
                float y2 = layersize.yMax;
                float x2 = GetValueFromY(y2);
                float x3 = 0 - layersize.xMax;
                float y3 = GetValueFromX(x3);
                float y4 = 0-layersize.yMax;
                float x4 = GetValueFromY(y4);

                //表示方程直线是垂直与x轴的，坐标点的y值取任意值
                if(y1==float.MaxValue)
                {
                    y1 = layersize.yMax;
                    y2 = 0;
                    y3 = 0-layersize.yMax;
                    x1 = GetValueFromY(y1);
                    x2 = GetValueFromY(y2);
                    x3 = GetValueFromY(y3);
                }
                //表示方程直线垂直于y轴，坐标点的值取任意值
                if(x2==float.MaxValue)
                {
                    x1 = layersize.xMax;
                    x2 = 0;
                    x3 = 0 - layersize.xMax;
                    y1 = GetValueFromX(x1);
                    y2 = GetValueFromX(y2);
                    y3 = GetValueFromX(y3);
                }

                PointF p1 = new PointF(x1, y1);
                if (CheckPointValidity(p1))
                    list_point.Add(p1);

                PointF p2 = new PointF(x2, y2);
                if (CheckPointValidity(p2))
                    list_point.Add(p2);

                PointF p3 = new PointF(x3, y3);
                if (CheckPointValidity(p3))
                    list_point.Add(p3);

                PointF p4 = new PointF(x4, y4);
                if (CheckPointValidity(p4))
                    list_point.Add(p4);

                //如果可用点数小于2两个，判断方程是否是
                if (list_point.Count < 2)
                    return;
                else
                {
                    PointF pixel_s = list_point[0];
                    PointF pixel_e = list_point[list_point.Count-1];
                    PointF startPoint = layersize.CoordinateToPixel(pixel_s);
                    PointF endPoint = layersize.CoordinateToPixel(pixel_e);
                    bg.DrawLine(pen, startPoint, endPoint);
                }
                // 如果显示tag状态是真执行tag绘制动作
                if(ShowTag)
                {
                    string taginfo = TagInfo;
                    PointF tagPoint = layersize.CoordinateToPixel(list_point[0]);
                    tagPoint.X += 10;
                    Brush b = new SolidBrush(TagColor);

                    bg.DrawString(taginfo, TagFont, b, tagPoint);
                }
                g.DrawImage(bmp,new Point(0,0));
            }
            catch(Exception e)
            {
                throw new Exception(string.Format("绘制直线方程出错,错误信息为:{0}", e.Message.ToString()));
            }
        }
        /// <summary>
        /// 通过x值获取x值
        /// </summary>
        /// <param name="x">x值</param>
        /// <returns>Y值</returns>
        public float GetValueFromX(float x)
        {
            float Y;
            //当B为0时直线直线垂直于X轴Y可取任意值，为了识别Y为其赋值为float的最大值
            if (B == 0)
            {
                Y = float.MaxValue;
            }
            else
            {
                Y = -A * x / B - C / B;
            }
            return Y;
        }

        /// <summary>
        /// 通过Y值获取X值
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        public float GetValueFromY(float y)
        {
            
            float X;
            // 当A为0时，直线为垂直于Y轴的直线，X可以取任意值，为识别X为其赋值为float的最大值
            if (A == 0)
            {
                X = float.MaxValue;
            }
            else
            {
                X = -B * y / A - C / A;
            }
            return X;
        }

        /// <summary>
        /// 返回返程字符串
        /// </summary>
        /// <returns>方程字符串</returns>
        public override string toString()
        {
            return TagInfo;
        }

        /// <summary>
        /// 校验坐标点是否可绘制
        /// </summary>
        /// <param name="p">坐标点</param>
        /// <param name="layersize">坐标系尺寸</param>
        /// <returns>校验结果</returns>
        public bool CheckPointValidity(PointF p)
        {
            bool result = false;
            try
            {
                bool xflag = false;
                bool yflag = false;
                if (p.X >= (0 - layersize.xMax) && p.X <= layersize.xMax)
                    xflag = true;
                if (p.Y >= (0 - layersize.yMax) && p.Y <= layersize.yMax)
                    yflag = true;

                result = xflag && yflag;
            }
            catch
            {
               
            }
            return result;
        }

        /// <summary>
        /// 返回方程类别
        /// </summary>
        /// <returns></returns>
        public LAYERTYPE GetEquationType()
        {
            return LAYERTYPE.LINE;
        }
        /// <summary>
        /// 擦除图像
        /// </summary>
        /// <param name="g"></param>
        public void Eraser(Graphics g)
        {
            throw new NotImplementedException();
        }
    }
}
